package antoine.ear.generator;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.ShortMessage;

import antoine.ear.exo.Exo;

public abstract class SequenceGenerator extends NoteGenerator {
	
	private static final int	VELOCITY = 64;
	protected int[] mode;
	protected String name = "";

	
	protected String soluce;
	public int tickOffset;

	
	public String getSoluce(){
		return soluce;
	}
	
	public String seqName() {
		return name;
	}
	
	public List generate(int nbNotes, int tona, int octave) {
		List res = new ArrayList();
		
		Random random = new Random();
		soluce = NoteGenerator.getNoteName(tona)+" "+seqName()+" ";
		
		for (int i=1;i<1+nbNotes;i++){
			int note = mode[random.nextInt(mode.length)];
			this.removeNoteInMode(note);
			name += NoteGenerator.getNoteName(note);
			
			soluce += NoteGenerator.getNoteName(note)+" ";
			res.add(createNoteOnEvent(note+12*octave+tona, i+tickOffset));
			res.add(createNoteOffEvent(note+12*octave+tona, i+1+tickOffset));
			res.add(createMetaMessOnEvent(note+12*octave+tona, i+tickOffset, Exo.ACTIVATENOTE));
			res.add(createMetaMessOnEvent(note+12*octave+tona, i+1+tickOffset, Exo.DESACTIVATENOTE));
		}
		
		return res;
	}
	
	public void removeNoteInMode(int note){
		for (int i=0;i<mode.length;i++){
			if(mode[i]==note){
				int[] newMode = new int[mode.length-1];
				int k=0;
				for (int j=0;j<mode.length;j++){
					if(mode[j]!=note){
						newMode[k]=mode[j];
						k++;
					}
				}
				this.mode = newMode;
			}
		}
	}
	
	public void addNoteInMode(int note){
		boolean found = false;
		for (int i=0;i<mode.length;i++){
			if(mode[i]==note){
				found=true;
			}
		}
		if(!found){
			int[] newMode = new int[mode.length+1];
			for (int j=0;j<mode.length;j++){
				newMode[j] = mode[j];
			}
			newMode[mode.length] = note;
			this.mode = newMode;
		}
	}
	
	protected MidiEvent createNoteOffEvent(int nKey, long lTick){
		return createNoteEvent(ShortMessage.NOTE_OFF, nKey,  0, lTick);
	}
	
	protected MidiEvent createNoteOnEvent(int nKey, long lTick) {
		return createNoteEvent(ShortMessage.NOTE_ON, nKey, VELOCITY, lTick);
	}

	protected MidiEvent createNoteEvent(int nCommand, int nKey, int nVelocity, long lTick)	{
		ShortMessage	message = new ShortMessage();
		try	{
			message.setMessage(nCommand, 0,	 nKey, nVelocity);
		}
		catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
		MidiEvent event = new MidiEvent(message,  lTick);
		return event;
	}
	
	protected MidiEvent createMetaMessOnEvent(int nKey, long lTick, int type)	{
		MetaMessage	message = new MetaMessage();
		try	{
			byte[] tab = new byte[1];
			tab[0] = (byte) nKey;
			message.setMessage(type, tab,	1);
		}
		catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
		MidiEvent event = new MidiEvent(message,  lTick);
		return event;
	}
}
